using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace Moussavi
{
    public class SerialCommManager : IDisposable
    {
        #region Data Members

        private String m_CommAddress;
        private SerialPort m_SerialPort;
        private String m_DeviceName;

        #endregion

        #region Ctor

        public SerialCommManager(String DeviceName)
        {
            m_SerialPort = new SerialPort();

            m_DeviceName = DeviceName;
            m_SerialPort.BaudRate = Properties.Settings.Default.SerialBaudRate;
            m_SerialPort.DataBits = Properties.Settings.Default.SerialDataBits;
            m_SerialPort.StopBits = Properties.Settings.Default.SerialStopBits;
            m_SerialPort.Parity = Properties.Settings.Default.SerialParity;
        }
        #endregion

        #region Public Mehtods

        public void OpenPort()
        {
            if (m_SerialPort.IsOpen)
                return;

            for (int i = 10; i < 20; i++)
            {
                String sCommAddress = "COM" + i.ToString();
                m_CommAddress = sCommAddress;

                m_SerialPort.PortName = m_CommAddress;

                try
                {
                    m_SerialPort.Open();
                }
                catch
                {
                    continue;
                }

                System.Threading.Thread.Sleep(200);

                // If we reached to here, some port is open
                // Lets check who is behind it
                m_SerialPort.Write(":IDN?:");

                System.Threading.Thread.Sleep(200);

                String ID = m_SerialPort.ReadExisting();

                // Compare with known device name
                if (ID.Contains(m_DeviceName))
                {
                    break;
                }
                else
                {
                    m_SerialPort.Close();
                }
            }

            if (!m_SerialPort.IsOpen)
            {
                throw new Exception("Device wasn't found!");
            }
        }


        public bool IsOpen()
        {
            return m_SerialPort.IsOpen;
        }
        
        public void ClosePort()
        {
            m_SerialPort.Close();
        }

        public String ReadMemoryContents(int iStart, int iLength)
        {

            return "";
        }

        public void WriteMemoryContents(int iStart, int iLength, String sData,  System.Windows.Forms.ProgressBar ProgressBar)
        {
            double pos;
            int i;
            double delta = 100.0/(double)(iLength);

            m_SerialPort.Write(":WRIT " + iStart + " " + iLength + ":");
            for (i = 0, pos = 0.0; i < iLength; i++, pos+=delta)
            {
                m_SerialPort.Write(sData.ToCharArray(), i, 1);
                System.Threading.Thread.Sleep(200);

                if (ProgressBar != null)
                    ProgressBar.Value = (int)(pos);
            }
            m_SerialPort.Write(":".ToCharArray(), 0, 1);
        }

        public void WritePictureContents(int iWidth, int iHeight, int iColorDepth, int IsRGB, char[][][] Picture, System.Windows.Forms.ProgressBar ProgressBar)
        {
            double pos;
            int iDepthPower = (int)(Math.Log((double)(iColorDepth), 2.0));
            double delta = 100.0 / (double)(iHeight * iWidth * iDepthPower / 8);

            System.Threading.Thread.Sleep(20);
            m_SerialPort.Write(":WRFI " + iWidth + " " + iColorDepth + ":");
            if (IsRGB == 1)     // Color Picture
            {
            }
            else        // BW Picture
            {
                int pixelPerByte = 8 / iDepthPower;
                pos = 0.0;

                for (int x = 0; x < iWidth; x++)
                {
                    for (int y = 0; y < iHeight; y += pixelPerByte)
                    {
                        // Update Progress Bar
                        pos += delta;
                        if (ProgressBar != null)
                            ProgressBar.Value = (int)(pos);

                        // Create new byte
                        byte[] newByte = new byte[1];
                        for (int k = pixelPerByte-1; k >= 0; k--)
                        {
                            newByte[0] = (byte)(newByte[0] << iDepthPower);
                            newByte[0] |= (byte)Picture[x][y + k][0];
                        }

                        System.Threading.Thread.Sleep(10);
                        m_SerialPort.Write(newByte, 0, 1);

                        String aa = m_SerialPort.ReadExisting();
                    }
                }
            }

            String bb = m_SerialPort.ReadExisting(); 

            m_SerialPort.Write(":".ToCharArray(), 0, 1);

            if (ProgressBar != null)
                ProgressBar.Value = 100;

        }

        public String ReadDeviceProperties()
        {
            m_SerialPort.Write(":IDN?:");
            System.Threading.Thread.Sleep(200);
            return m_SerialPort.ReadExisting();
        }

        public void LeaveDevice()
        {
            m_SerialPort.Write(":EXIT:");
        }

        #endregion 

    
        #region IDisposable Members

        public void Dispose()
        {
            if (m_SerialPort.IsOpen)
            {
                m_SerialPort.Write(":EXIT:");
                m_SerialPort.Close();
            }
        }

        #endregion
    }
}
